package cn.edu.nju.software.cdiy.algorithm.assessor;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import cn.edu.nju.software.cdiy.bean.CPU;
import cn.edu.nju.software.cdiy.bean.Disk;
import cn.edu.nju.software.cdiy.bean.Driver;
import cn.edu.nju.software.cdiy.bean.Graphics;
import cn.edu.nju.software.cdiy.bean.HardwareSet;
import cn.edu.nju.software.cdiy.bean.MB_MemFrequency;
import cn.edu.nju.software.cdiy.bean.MainBoard;
import cn.edu.nju.software.cdiy.bean.Memory;
import cn.edu.nju.software.cdiy.bean.NetworkAdapter;
import cn.edu.nju.software.cdiy.bean.Power;
import cn.edu.nju.software.cdiy.bean.SoundCard;
import cn.edu.nju.software.cdiy.service.UtilService;
import cn.edu.nju.software.cdiy.util.NumberFormatter;

public class PerformanceAssessor implements Assessor<PerformanceMessager> {
	
	private UtilService utilService;
	private SessionFactory sessionFactory;
	
	public void setUtilService(UtilService utilService) {
		this.utilService = utilService;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	@Override
	public PerformanceMessager generateAssess(HardwareSet hardwareSet) {
		HardwareSet hs = utilService.fillHardwareSet(hardwareSet);
		// 待返回的messager
		
		PerformanceMessager pm = new PerformanceMessager();

		if (hs.getMemory() != null)
			memAssess(hs, pm);
		if (hs.getGraphics() != null)
			graAssess(hs, pm);
		if (hs.getCpu() != null)
			cpuAssess(hs, pm);

		bottleneckDetect(hs, pm);
		matchDetect(hs, pm);
		numberDetect(hs, pm);

		return pm;
	}

	private void numberDetect(HardwareSet hs, PerformanceMessager pm) {
		/*
		 * 对于内存和硬盘的接口数量以及已经选择的硬件集合里面的内存和硬盘数量进行判断 若超出了则出现了硬件数量溢出错误 弹出错误信息并提示改正
		 * 
		 * *（有待扩展）
		 */
		if (hs.getMainBoard() != null) {
			String nummes = "数量限制：";
			MainBoard mb = hs.getMainBoard();
			int memSlotNum = mb.getMemSlotNum();
			
			if (hs.getMemory()!=null) {
				//detect the num of mem
				if (hs.getMemoryNum() > memSlotNum) {
					nummes += "内存数量超出主板能支持内存接口的最大值，建议重新选择主板或减少内存数量";
				}
			}
			pm.setNumberMessage(nummes);
		}

	}

	private void matchDetect(HardwareSet hs, PerformanceMessager pm) {
		/*
		 * 对由于硬件选择顺序而导致的当时匹配，未来却不一定匹配的情况进行分析处理 电源功率与硬件功率总和的顺序导致的不匹配问题
		 * 
		 * *（有待扩展）
		 */
		if (hs.getPower() != null) {
			String matchmes = "匹配限制：";
			// 获取电源的额定功率
			Power nowPw = hs.getPower();
			int powerRatedPower = nowPw.getRatedPower();
			// 获取对电源有影响的硬件功率总和
			int totalPower = 0;
			if (hs.getCpu() != null) {
				CPU cpu = hs.getCpu();
				int cpuPower = cpu.getRatedPower();
				totalPower = totalPower + cpuPower;
			}
			if (hs.getDisk() != null) {
				Disk disk = hs.getDisk();
				int diskPower = disk.getRatedPower();
				totalPower = totalPower + diskPower;
			}
			if (hs.getDriver() != null) {
				Driver dri = hs.getDriver();
				int driPower = dri.getRatedPower();
				totalPower = totalPower + driPower;
			}
			if (hs.getGraphics() != null) {
				Graphics Gra = hs.getGraphics();
				int graPower = Gra.getRatedPower();
				totalPower = totalPower + graPower;
			}
			if (hs.getMainBoard() != null) {
				MainBoard mb = hs.getMainBoard();
				int mbPower = mb.getRatedPower();
				totalPower = totalPower + mbPower;
			}
			if (hs.getMemory() != null) {
				Memory mem = hs.getMemory();
				int memPower = mem.getRatedPower();
				totalPower = totalPower + memPower;
			}
			if (hs.getNetworkAdapter() != null) {
				NetworkAdapter na = hs.getNetworkAdapter();
				int naPower = na.getRatedPower();
				totalPower = totalPower + naPower;
			}
			if (hs.getSoundCard() != null) {
				SoundCard sc = hs.getSoundCard();
				int scPower = sc.getRatedPower();
				totalPower = totalPower + scPower;
			}

			if (totalPower <= powerRatedPower) {
				matchmes += "电源依然适合目前的硬件集合，电源匹配时没有遇到功率瓶颈";
			} else
				matchmes += "电源已不适合目前的硬件集合，电源匹配时遇到功率瓶颈，取硬件顺序电源过于靠前，建议最后选电源";
			
			pm.setMatchMessage(matchmes);
		}
		
	}

	private void bottleneckDetect(HardwareSet hs, PerformanceMessager pm) {
		/*
		 * 对hs的信息进行分析，检测是否存在性能瓶颈
		 */
		
		/*
		 * 关键的性能瓶颈有以下几点： 内存与主板的频率差距太大 无法发挥内存的最大性能
		 * 
		 * *（有待扩展） 本方法体如果过长，可以参考filter进行分离 目前只有一个检测点 暂时可以放在一起
		 * 
		 * 后期进行更加细致的配置优化方案 如果检查性能瓶颈的关键部件还不存在于hs之中，则直接return
		 */
		if (hs.getMainBoard() != null && hs.getMemory() != null) {
			String botneckmes = "性能瓶颈：";
			// 获得内存的频率值
			Memory mem = hs.getMemory();
			double mF = NumberFormatter.getNumber(mem.getMemFrequency()
					.getValue());
			// 获得主板能支持的内存频率列表
			MainBoard mb = hs.getMainBoard();
			Session sess = sessionFactory.getCurrentSession();
			int id = mb.getId();
			String sql = "FROM MB_MemFrequency WHERE MB=" + id;
			List<MB_MemFrequency> list = sess.createQuery(sql).list();

			for (int i = 0; i < list.size(); i++) {
				// 遍历内存频率列表获取具体值
				double mb_mF = NumberFormatter.getNumber(list.get(i)
						.getMemFrequency().getValue());
				if (mF < mb_mF) {
					// 先确定主板支持的内存频率必须高于内存的频率
					// System.out.println("该内存初步判断合适该主板");
					if ((mb_mF - mF) >= 200) {
						// 若主板支持的内存频率高于内存频率200以上（含），则主板的性能无法被最大程度发挥，遇到了瓶颈
						botneckmes += "主板性能无法最大发挥，收到了内存频率瓶颈的影响。";
					} else
						// 若主板支持的内存频率低于内存频率200以下，则主板的性能被最大程度发挥，配置非常合适
						botneckmes += "主板性能最大发挥，配置非常适当。";
				}
			}
			pm.setPerformanceBottleneck(botneckmes);
		}

	}

	private void cpuAssess(HardwareSet hs, PerformanceMessager pm) {
		// 根据hs获得的信息 对pm的cpuMessage进行set操作
		CPU cpu = hs.getCpu();
		String cpumes = "CPU评估：";

		// 根据CPU制造工艺影响CPU性能的情况，制造工艺越先进，CPU性能越好，以主流工艺32nm为区分点
		if (cpu.getManuTech().getKey() == 172) 
			cpumes += "cpu主流制造工艺，";
		else if (cpu.getManuTech().getKey() > 172)
			cpumes += "cpu制造工艺稍落后，";
		else
			cpumes += "cpu制造工艺相当先进，";

		// 根据CPU核心数量判断CPU性能，核心数量越多，CPU性能越好，以主流双核为区分点
		if (cpu.getCoreNum().getKey() == 922)
			cpumes = cpumes + "主流双核核心，";
		else if (cpu.getCoreNum().getKey() < 922)
			cpumes = cpumes + "单核核心偏落后，";
		else
			cpumes = cpumes + "多核核心相当先进，";

		// 根据主频大小判断CPU性能，主频越高，CPU性能越好，以主流双核为区分点
		if (cpu.getMasterFrequency() >= 1.6
				&& cpu.getMasterFrequency() <= 3)
			cpumes = cpumes + "cpu主频为主流配置，";
		else if (cpu.getMasterFrequency() < 1.6)
			cpumes = cpumes + "cpu主频偏低，";
		else
			cpumes = cpumes + "cpu主频很高，";

		// 根据二级缓存大小判断CPU性能，二级缓存越高，CPU性能越好，以主流二级缓存大小为区分点
		if (cpu.getBrand().getId() == 1) {
			if (cpu.getL2().getKey() >= 209)
				cpumes = cpumes + "是intel的主流CPU缓存配置，";
			else
				cpumes = cpumes + "低于intel的主流CPU缓存配置，";
		}
		else if (cpu.getBrand().getId() == 2) {
			if (cpu.getL2().getKey() >= 207
					&& cpu.getL2().getKey() <= 210)
				cpumes = cpumes + "是intel的主流CPU缓存配置；";
			else if (cpu.getL2().getKey() < 207)
				cpumes = cpumes + "低于AMD的主流CPU缓存配置；";
			else
				cpumes = cpumes + "高于AMD的主流CPU缓存的高端配置；";
		}
		pm.setCpuMessage(cpumes);
	}

	private void graAssess(HardwareSet hs, PerformanceMessager pm) {
		// 根据hs获得的信息 对pm的graMessage进行set操作
		Graphics gra = hs.getGraphics();
		String grames = "显卡评估：";

		// 根据显卡类型影响显卡性能的情况，显卡类型越先进，显卡性能越好，以GDDR3为区分点
		if (hs.getGraphics().getVideoMemType().getKey() >= 407)
			grames += "达到了目前的主流显卡类型标准，";
		else if (hs.getGraphics().getVideoMemType().getKey() < 407)
			grames += "低于目前的主流星卡类型标准，";

		// 根据显卡芯片制造工艺影响显卡性能的情况，制造工艺越先进，显卡性能越好，以主流工艺40nm为区分点
		if (hs.getGraphics().getManuTech().getKey() == 381)
			grames = grames + "是目前的显卡主流制造工艺，";
		else if (hs.getGraphics().getManuTech().getKey() != 381)
			grames = grames + "不是显卡的主流制造工艺，略落后，";

		// 根据显卡的显存容量影响显卡性能的情况，显存容量越大，显卡性能越好，以1G为区分点
		if (hs.getGraphics().getVideoMemCapacity().getKey() >= 420)
			grames = grames + "显存容量达到主流水平，";
		else if (hs.getGraphics().getVideoMemCapacity().getKey() < 420)
			grames = grames + "显存容量低于主流水平，";

		// 根据显卡的显存位宽影响显卡性能的情况，显存位宽越大，显卡性能越好，以256bit为区分点
		if (hs.getGraphics().getVideoMemBitWide().getKey() >= 394)
			grames = grames + "显存位宽达到主流标准；";
		else if (hs.getGraphics().getVideoMemBitWide().getKey() < 394)
			grames = grames + "显存位宽低于主流标准；";

		pm.setGraMessage(grames);
	}

	private void memAssess(HardwareSet hs, PerformanceMessager pm) {
		// 根据hs获得的信息 对pm的memMessage进行set操作
		Memory mem = hs.getMemory();
		String memmes = "内存评估：";

		// 根据内存型号影响内存性能的情况，内存型号越先进，内存速度越快，以GDDR3为区分点
		if (hs.getMemory().getMemType().getKey() == 233)
			memmes += "是目前的主流内存类型标准，";
		else if (hs.getMemory().getMemType().getKey() < 233)
			memmes += "低于目前的主流内存类型标准，";

		// 如果内存的大小介于2G和4G之间，则说明内存容量达到主流水平，低于2G则为内存偏小，高于4G则为内存功能强大
		if (hs.getMemory().getMemCapacity().getKey() < 267)
			memmes = memmes + "内存容量很大，";
		else if (hs.getMemory().getMemCapacity().getKey() > 268)
			memmes = memmes + "内存容量偏小，";
		else if (hs.getMemory().getMemCapacity().getKey() == 267
				|| hs.getMemory().getMemCapacity().getKey() == 268)
			memmes = memmes + "内存容量达到主流水平，";

		// 根据内存的数量判断内存的性能，大于一条为高级配置
		if (hs.getMainBoard() != null) {
			int n = NumberFormatter.getPriceArray(mem.getMemCapacityDes())[0];
			if (n > 1) {
				memmes = memmes + "内存数量高于1条，内存性能大大提高，";
			} else
				memmes = memmes + "内存数量为1条，属于主流内存配置，";
		}

		// 根据不同型号的内存的频率的大小来衡量内存的性能，以DDR3和DDR2的两个主流范围为区分
		if (hs.getMemory().getMemType().getKey() == 233) {
			if (hs.getMemory().getMemFrequency().getKey() == 242
					|| hs.getMemory().getMemFrequency().getKey() == 243)
				memmes = memmes + "是DDR3类型内存的主流频率；";
			else if (hs.getMemory().getMemFrequency().getKey() < 242)
				memmes = memmes + "超越了DDR3类型内存的主流频率的高频率；";
			else if (hs.getMemory().getMemFrequency().getKey() > 243)
				memmes = memmes + "低于DDR3类型内存的主流频率；";
		}
		if (hs.getMemory().getMemType().getKey() == 232) {
			if (hs.getMemory().getMemFrequency().getKey() == 245
					|| hs.getMemory().getMemFrequency().getKey() == 246)
				memmes = memmes + "是DDR2类型内存的主流频率；";
			else if (hs.getMemory().getMemFrequency().getKey() < 245)
				memmes = memmes + "超越了DDR2类型内存的主流频率的高频率；";
			else if (hs.getMemory().getMemFrequency().getKey() > 246)
				memmes = memmes + "低于DDR2类型内存的主流频率；";
		}

		pm.setMemMessage(memmes);
	}

}
